package cn.tedu.vue_master.oauth2;

import cn.tedu.vue_master.mapper.OAuthClientMapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.oauth2.provider.*;
import org.springframework.security.oauth2.provider.client.BaseClientDetails;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
@Slf4j
public class OAuthClientServiceImpl implements OAuthClientService,
        ClientDetailsService, ClientRegistrationService {
    private final OAuthClientMapper oAuthClientMapper;


    @Override
    public Boolean hasPermission(HttpServletRequest request, OAuth2Authentication authentication) {

        String clientId = authentication.getOAuth2Request().getClientId();

        LambdaQueryWrapper<OAuthClientEntity> lambdaQueryWrapper = new LambdaQueryWrapper();
        log.debug("clientId={}", clientId);
        lambdaQueryWrapper.eq(StringUtils.hasText(clientId), OAuthClientEntity::getClientId, clientId);
        OAuthClientEntity clientEntity = oAuthClientMapper.selectOne(lambdaQueryWrapper);
        String[] webServerRedirectUris = clientEntity.getWebServerRedirectUri().split(",");
        Set<String> urls = Arrays.stream(webServerRedirectUris).collect(Collectors.toSet());
        //urls.add("GET /oauth/token");

        if (urls.size() > 0) {
            return urls.stream().anyMatch(
                    url -> url.equalsIgnoreCase(request.getMethod()+" " + request.getServletPath())
            );
        }

        return false;
    }

    /**
     * 根据客户端ID查询客户端
     *
     * @param clientId 客户端ID
     * @return 客户端
     */
    @Override
    public ClientDetails loadClientByClientId(String clientId) {
        // TODO 根据 clientId 查询数据库数据，
        //  组装出 ClientDetails 返回
        //  （注意这里的常量值都应该是数据库查询出来的）
        if (!StringUtils.hasText(clientId)) {
            return null;
        }
        LambdaQueryWrapper<OAuthClientEntity> lambdaQueryWrapper = new LambdaQueryWrapper();
        lambdaQueryWrapper.eq(StringUtils.hasText(clientId), OAuthClientEntity::getClientId, clientId);
        OAuthClientEntity clientEntity = oAuthClientMapper.selectOne(lambdaQueryWrapper);
        log.info("查询得到的OAuthClientEntity={}", clientEntity);
        if (clientEntity == null) {
            throw new NoSuchClientException(String.format("No client with requested id: %s", clientId));
        }
        return convertClient(clientEntity);
    }

    private BaseClientDetails convertClient(OAuthClientEntity oAuthClientEntity) {
        log.info("开始转换OAuthClientEntity为BaseClientDetails");
        BaseClientDetails baseClientDetails = new BaseClientDetails(
                oAuthClientEntity.getClientId(), oAuthClientEntity.getResourceIds(),
                oAuthClientEntity.getScope(), oAuthClientEntity.getAuthorizedGrantTypes(),
                oAuthClientEntity.getAuthority(), oAuthClientEntity.getWebServerRedirectUri()
        );
        // 设置客户端访问密钥
        baseClientDetails.setClientSecret(oAuthClientEntity.getClientSecret());
        // 设置accessToken有效时间
        if (oAuthClientEntity.getAccessTokenValidity() != null) {
            baseClientDetails.setAccessTokenValiditySeconds(oAuthClientEntity.getAccessTokenValidity());
        }
        // 设置refreshToken有效时间
        if (oAuthClientEntity.getRefreshTokenValidity() != null) {
            baseClientDetails.setRefreshTokenValiditySeconds(oAuthClientEntity.getRefreshTokenValidity());
        }

        log.info("转换后得到的baseClientDetails={}", baseClientDetails);
        return baseClientDetails;
    }

    /**
     * 根据客户端ID查询
     *
     * @param clientEntity 客户端ID
     * @return 执行结果
     */
    @Override
    public OAuthClientEntity findByClientId(OAuthClientEntity clientEntity) {
        return null;
    }

    /**
     * 根据客户端ID修改
     *
     * @param clientEntity 客户端ID
     * @return 执行结果
     */
    @Override
    public int updateByClientId(OAuthClientEntity clientEntity) {
        return 0;
    }

    /**
     * 添加客户端
     * @param clientDetails
     * @throws ClientAlreadyExistsException
     */
    @Override
    public void addClientDetails(ClientDetails clientDetails) throws ClientAlreadyExistsException {

    }

    /**
     * 修改客户端
     * @param clientDetails
     * @throws ClientAlreadyExistsException
     */
    @Override
    public void updateClientDetails(ClientDetails clientDetails) throws NoSuchClientException {

    }

    @Override
    public void updateClientSecret(String s, String s1) throws NoSuchClientException {

    }

    @Override
    public void removeClientDetails(String s) throws NoSuchClientException {

    }

    @Override
    public List<ClientDetails> listClientDetails() {
        return null;
    }
}
